home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 19.zip / BS1 part 19 / Lattice C disk 4.adf / source / catch.a < prev    next >
Text File  |  1988-11-07  |  24KB  |  980 lines

  1. * C initial startup procedure under AmigaDOS
  2. *
  3. * Use the following command line to make catch.o
  4. * asm -u -iINCLUDE: catch.a
  5. *
  6. * Use the following command line to make catchres.o
  7. * asm -u -iINCLUDE: -dRESIDENT -ocatchres.o catch.a
  8. *
  9. * Use the following command line to make catchresnr.o
  10. * asm -u -iINCLUDE: -dRESIDENT -dNOREQ -ocatchresnr.o catch.a
  11. *
  12.  
  13.     INCLUDE "exec/types.i"
  14.     INCLUDE "exec/alerts.i"
  15.     INCLUDE "exec/nodes.i"
  16.     INCLUDE "exec/lists.i"
  17.     INCLUDE "exec/ports.i"
  18.     INCLUDE "exec/libraries.i"
  19.     INCLUDE "exec/tasks.i"
  20.  
  21.     INCLUDE "exec/memory.i"
  22.     INCLUDE "exec/execbase.i"
  23.     INCLUDE "libraries/dos.i"
  24.     INCLUDE "libraries/dosextens.i"
  25.     INCLUDE "workbench/startup.i"
  26.     INCLUDE "intuition/intuition.i"
  27.         INCLUDE "exec/funcdef.i"
  28.         INCLUDE "exec/exec_lib.i"
  29.         INCLUDE "libraries/dos_lib.i"
  30.  
  31. VERSION     equ    1
  32. REVISION    equ    0
  33.  
  34. CATCH        set    1
  35.         IFND NOREQ
  36. AUTOREQ     set    1
  37.         ENDC
  38.  
  39.  
  40. MEMFLAGS EQU    MEMF_CLEAR+MEMF_PUBLIC
  41. AbsExecBase EQU 4
  42.  
  43. callsys macro
  44.         CALLLIB _LVO\1
  45.         endm
  46.  
  47.     xdef    XCEXIT                ; exit(code) is standard way to leave C.
  48.     xdef     @XCEXIT
  49.  
  50.     xref    LinkerDB            ; linker defined base value
  51.     xref    _BSSBAS             ; linker defined base of BSS
  52.     xref    _BSSLEN             ; linker defined length of BSS
  53.  
  54.     IFD    RESIDENT
  55.     xref    RESLEN
  56.     xref    RESBASE
  57.     xref    NEWDATAL
  58.     ENDC
  59.  
  60. *    library references
  61.  
  62.         section   text,code
  63.  
  64.     xref    _main            * Name of C program to start with.
  65.     xref    MemCleanup
  66.         xref    __fpinit                * initialize floating point
  67.         xref    __fpterm                * terminate floating point
  68.  
  69. start:
  70.     movem.l d1-d6/a0-a6,-(a7)
  71. REGSIZE EQU    (6+7)*4
  72.     lea    REGSIZE(a7),A5            ; determine old stack pointer
  73.     move.l    a0,a2                ; save command pointer
  74.     move.l    d0,d2                ; and command length
  75.     lea    LinkerDB,a4            ; load base register
  76.     
  77.     IFND    RESIDENT
  78.         lea     _BSSBAS,a3                    * get base of BSS
  79.         moveq   #0,d1
  80.         move.l  #_BSSLEN,d0            * get length of BSS in longwords
  81.         bra.s   clr_lp                 * and clear for length given
  82. clr_bss move.l  d1,(a3)+
  83. clr_lp  dbf     d0,clr_bss
  84.     ENDC
  85.     
  86.     IFD    RESIDENT
  87.     move.l    AbsExecBase.W,a6
  88.         movem.l     d0-d1/a0-a2,-(a7)
  89.     sub.l        #RESBASE,a4
  90.     move.l        #RESLEN,d0
  91.     move.l        #MEMFLAGS,d1
  92.     callsys        AllocMem
  93.     tst.l            d0
  94.     beq.w        abort
  95.     move.l        d0,a0
  96.     move.l        d0,a2
  97. ;a2 now has difference
  98.     move.l        d0,a1
  99.     move.l        #NEWDATAL,d0
  100. ;copy data over
  101. cpy:    move.l        (a4)+,(a0)+
  102.     subq.l        #1,d0
  103.     bne        cpy
  104. ;a4 now points at number of relocs
  105.     move.l        (a4)+,d0
  106. reloc:    beq.s        nreloc
  107.     move.l        a1,a0
  108.     add.l        (a4)+,a0            ; a0 now has add of reloc
  109.     add.l        (a0),a2
  110.     move.l        a2,(a0)
  111.     move.l        a1,a2            ; restore offset
  112.     subq.l        #1,d0
  113.     bra.s        reloc
  114.  
  115. nreloc: move.l        a1,a4            ; set up new base register
  116.     add.l        #RESBASE,a4
  117.         movem.l       (A7)+,d0-d1/a0-a2
  118.     ENDC
  119.  
  120.     move.l    AbsExecBase.W,a6
  121.     move.l    a6,SysBase(A4)
  122.  
  123.     ifd    CATCH
  124.     move.w    AttnFlags(a6),Environment+2(a4) ; save copy for dump
  125.     endc
  126.  
  127.     move.l    a7,_StackPtr(A4)        ; Save stack ptr
  128.     clr.l    WBenchMsg(A4)
  129.  
  130. *------ attempt to open DOS library:
  131.     bsr.w    openDOS
  132.  
  133.     ifd    CATCH
  134.      ifd     AUTOREQ
  135. *------ attempt to open Intuition library:
  136.         bsr.w        openIntui
  137.      endc
  138.     endc
  139.  
  140. *-----  clear any pending signals
  141.     moveq    #0,d0
  142.     move.l    #$00003000,d1
  143.     callsys    SetSignal
  144.  
  145. *------ get the address of our task
  146.     move.l    ThisTask(a6),A3
  147.  
  148.     ifd    CATCH
  149.     move.l    A3,TaskID(a4)
  150.  
  151. *------ initialize exception handler
  152. *------ Remember to preserve the old handler first
  153.         move.l  TC_TRAPDATA(a3),oldtrapdata(A4)
  154.     move.l    TC_TRAPCODE(a3),d0        ; check current exception
  155.         move.l  d0,oldtrapcode(A4)
  156.     swap    d0
  157.     cmpi.w    #$fb,d0             ; see if points to ROM
  158.     ble.s    1$                ; somebody else (debugger?) has vector
  159.     move.l    #Exception,TC_TRAPCODE(a3)    ; install pointers to code
  160.     move.l    a4,TC_TRAPDATA(a3)        ; ...and data
  161. 1$:
  162.     endc
  163.  
  164. *------ are we running as a son of Workbench?
  165.     move.l    pr_CurrentDir(A3),curdir(A4)
  166.     tst.l    pr_CLI(A3)
  167.     beq    fromWorkbench
  168.  
  169. *=======================================================================
  170. *====== CLI Startup Code ===============================================
  171. *=======================================================================
  172. *
  173. * Entry: D2 = command length
  174. *     A2 = Command pointer
  175. fromCLI:
  176.     ifd    CATCH
  177.     moveq    #-1,d0
  178.     move.l    d0,Starter(a4)        ; non-zero means CLI
  179.     move.l    a5,StackTop(a4)
  180.     endc
  181.  
  182.     move.l    a5,D0            ; get top of stack
  183.     sub.l    4(a5),D0        ; compute bottom
  184.     add.l    #128,D0         ; allow for parms overflow
  185.     move.l    D0,_base(A4)        ; save for stack checking
  186.  
  187. *------ find command name:
  188.     move.l    pr_CLI(a3),a0
  189.     add.l    a0,a0        * bcpl pointer conversion
  190.     add.l    a0,a0
  191.     move.l    cli_CommandName(a0),a1
  192.     IFND    AUTOREQ
  193.     move.l    cli_StandardOutput(a0),GConsole(a4)    * save output fh
  194.     ENDC
  195.     add.l    a1,a1        * bcpl pointer conversion
  196.     add.l    a1,a1
  197.  
  198. *------ collect parameters:
  199.     move.l    d2,d0            * get command line length
  200.     moveq.l #0,d1
  201.     move.b    (a1)+,d1
  202.     move.l    a1,_ProgramName(A4)
  203.     add.l    d1,d0            * add length of command name
  204.     addq.l    #1,d0            * allow for space after command
  205.  
  206.     clr.w    -(A7)            * set null terminator for command line
  207.     addq.l    #1,D0            * force to even number of bytes
  208.     andi.w    #$fffe,D0        *(round up)
  209.     sub.l    D0,A7            * make room on stack for command line
  210.     subq.l    #2,D0
  211.  
  212.     clr.w    0(A7,D0)
  213.  
  214. *------ copy command line onto stack
  215.     move.l    d2,d0            * get command line length
  216.     subq.l    #1,d0
  217.     add.l    d1,d2
  218.  
  219. copy_line:
  220.     move.b    0(A2,D0.W),0(A7,D2.W)    * copy command line to stack
  221.     subq.l    #1,d2
  222.     dbf    d0,copy_line
  223.     move.b    #' ',0(a7,d2.w)     * add space between command and parms
  224.     subq.l    #1,d2
  225.  
  226. copy_cmd:
  227.     move.b    0(a1,d2.w),0(a7,d2.w)    * copy command name to stack
  228.     dbf    d2,copy_cmd
  229.     move.l    A7,A1
  230.     move.l    A1,-(A7)        * push command line address
  231.     bra.w    main            * call C entrypoint
  232.  
  233. *=======================================================================
  234. *====== Workbench Startup Code =========================================
  235. *=======================================================================
  236.  
  237. fromWorkbench:
  238.     move.l    TC_SPLOWER(a3),_base(A4)    * set base of stack
  239.         add.l   #128,_base(A4)             * allow for parms overflow
  240.  
  241.     ifd    CATCH
  242.     move.l    TC_SPUPPER(a3),StackTop(a4)    ; set top of stack
  243.     endc
  244.  
  245. *------ we are now set up.  wait for a message from our starter
  246.         lea     pr_MsgPort(A3),a0       * our process base
  247.         callsys WaitPort
  248.         lea     pr_MsgPort(A3),a0       * our process base
  249.         callsys GetMsg
  250.         move.l  d0,WBenchMsg(a4)
  251.         move.l  d0,-(SP)
  252. *
  253.     move.l    d0,a2            * get first argument
  254.     move.l    sm_ArgList(a2),d0
  255.     beq.s    do_cons
  256.     move.l    DOSBase(a4),a6
  257.     move.l    d0,a0
  258.     move.l    wa_Lock(a0),d1
  259.     move.l    d1,curdir(A4)
  260.     callsys    CurrentDir
  261. do_cons:
  262.     move.l    sm_ToolWindow(a2),d1    * get the window argument
  263.     beq.s    do_main
  264.     move.l    #MODE_OLDFILE,d2
  265.     callsys    Open
  266.     move.l    d0,stdin(a4)
  267.     beq.s    do_main
  268.     lsl.l    #2,d0
  269.     move.l    d0,a0
  270.     move.l    fh_Type(a0),pr_ConsoleTask(A3)
  271. do_main:
  272.     move.l    WBenchMsg(A4),a0    * get address of workbench message
  273.     move.l    a0,-(a7)        * push argv
  274.     pea    NULL(a4)        * push argc
  275.     move.l    sm_ArgList(a0),a0    * get address of arguments
  276.     move.l    wa_Name(a0),_ProgramName(A4)    * get name of program
  277.  
  278. *=============================================
  279. *------ common code --------
  280. *=============================================
  281.  
  282. main    jsr     __fpinit(PC)            * Initialize floating point
  283.     jsr    _main(PC)        * call C entrypoint
  284.     moveq.l #0,d0            * set successful status
  285.     bra.s    exit2
  286. *
  287.  
  288. XCEXIT:
  289.     move.l    4(SP),d0    * extract return code
  290. @XCEXIT
  291. exit2:
  292.     move.l    d0,-(a7)
  293.  
  294.     move.l    _ONEXIT(A4),d0    * exit trap function?
  295.     beq.s    exit3
  296.     move.l    d0,a0
  297.     jsr    (a0)
  298. exit3:
  299.     jsr    MemCleanup(PC)        ; cleanup leftover memory alloc.
  300.  
  301.     move.l    AbsExecBase.W,a6
  302.  
  303. *------ Restore the original exception handler
  304.     move.l    ThisTask(a6),A3
  305.         move.l  oldtrapdata(A4),TC_TRAPDATA(a3)
  306.     move.l    oldtrapcode(A4),TC_TRAPCODE(a3)    ; check current exception
  307.  
  308.     move.l    DOSBase(A4),a1
  309.     callsys    CloseLibrary        ; close Dos library
  310.  
  311.     ifd    CATCH
  312.      ifd     AUTOREQ
  313.         move.l    IntuiBase(a4),a1
  314.         callsys        CloseLibrary        ; close Intuition library
  315.      endc
  316.     endc
  317.  
  318.         jsr     __fpterm(PC)            * clean up any floating point
  319.  
  320. done_1c:
  321. *------ if we ran from CLI, skip workbench cleanup:
  322.     tst.l    WBenchMsg(A4)
  323.     beq.s    exitToDOS
  324.     move.l    stdin(A4),d1
  325.     beq.s    done_4
  326.     callsys    Close
  327. done_4:
  328.  
  329. *------ return the startup message to our parent
  330. *    we forbid so workbench can't UnLoadSeg() us
  331. *    before we are done:
  332.     move.l    AbsExecBase.W,A6
  333.     callsys    Forbid
  334.     move.l    WBenchMsg(a4),a1
  335.     callsys    ReplyMsg
  336.  
  337. *------ this rts sends us back to DOS:
  338. exitToDOS:
  339.     IFD    RESIDENT
  340.     move.l    #RESLEN,d0
  341.     move.l    a4,a1
  342.     sub.l    #RESBASE,a1
  343.     move.l    AbsExecBase.W,a6
  344.     callsys    FreeMem
  345.     ENDC
  346.  
  347.  
  348.     
  349.     MOVE.L    (A7)+,D0
  350.     movea.l _StackPtr(a4),SP    * restore stack ptr
  351.     movem.l (a7)+,d1-d6/a0-a6
  352.     rts
  353.  
  354.     IFD    RESIDENT
  355. abort:
  356.         movem.l     (a7)+,d0-d1/a0-a2
  357.     rts
  358.     ENDC
  359.     
  360. *-----------------------------------------------------------------------
  361. noDOS:
  362.         moveq.l #100,d0
  363.         bra.w    exit2
  364.  
  365.  
  366. *-----------------------------------------------------------------------
  367. *    Open the DOS library:
  368.  
  369. openDOS
  370.         lea    DOSName(PC),A1
  371.         moveq.l #0,D0
  372.         callsys    OpenLibrary
  373.         move.l    D0,DOSBase(A4)
  374.         beq.s    noDOS
  375.         rts
  376. DOSName     dc.b    'dos.library',0
  377.  
  378.     ifd    CATCH
  379. *-----------------------------------------------------------------------
  380. *    Open the Intuition library:
  381.  
  382. openIntui:
  383.         lea    IntuiName(PC),A1
  384.         moveq.l #0,D0
  385.         callsys    OpenLibrary
  386.         move.l    D0,IntuiBase(A4)
  387.         beq.s    noDOS
  388.         rts
  389. IntuiName    dc.b    'intuition.library',0
  390.  
  391. *-----------------------------------------------------------------------
  392. *    The Exception Handler - catches GURUs and exits (semi)cleanly
  393. Exception:
  394.     move.l    AbsExecBase.W,a0
  395.     move.l    ThisTask(a0),a0
  396.     move.l    TC_TRAPDATA(a0),a0        ; ...and data
  397.  
  398.     move.l    (a7)+,d0        ; get exception # from stack
  399.     move.l    d0,GURUNum(a0)        ; and save it
  400.     cmpi.l    #3,d0            ; ADDRESS or BUS error?
  401.     bgt.s    2$            ; no, skip adjustment
  402.     btst    #0,Environment+3(a0)    ; is it 68010 or 68020?
  403.     beq.s    1$            ; 0 means NO
  404.     bset    #7,8(a7)        ; set Rerun flag
  405.     bra.s    2$
  406. 1$:
  407.     addq.l    #8,a7            ; adjust for 68000
  408. 2$:
  409.     move.l    2(a7),d0        ; get PC at crash
  410.     move.l    d0,GURUAddr(a0)        ; and save it
  411.     move.l    #GURUExit,2(a7)        ; use our own exit point
  412.     rte
  413.  
  414. *-----------------------------------------------------------------------
  415. *    The Exception exit routine - write 'PGTB' IFF chunk to file
  416. *    'SnapShot.TB' in current directory, then exit to system.
  417.  
  418. GURUExit:
  419.     movem.l d0-d7/a0-a7,-(sp)    ; save all registers
  420.     move.l    AbsExecBase.W,a6    ; make sure we are working with Exec
  421.     callsys    GetCC            ; safe way - works with all CPUs
  422.     move.l    ThisTask(a6),a3
  423.     move.l    TC_TRAPDATA(a3),a4    ; make sure we have a valid # in a4
  424.     move.l    d0,Flags(a4)        ; save area
  425.     movem.l (sp)+,d0-d7
  426.     movem.l d0-d7,DDump(a4)        ; save data reg contents
  427.     movem.l (sp)+,d0-d7
  428.     movem.l d0-d7,ADump(a4)        ; save address reg contents
  429.     tst.l    StackPtr(a4)        ; if there's something there
  430.     bne    GExit1            ; ...we've been here before!
  431.     lea    TempStore(a4),a0    ; calculate addr of TempStore
  432.     move.l    a0,TempAddr(a4)        ; ...and save for later access
  433.     move.l    A7Store(a4),d0        ; make sure we have proper TOS
  434.     move.l    d0,StackPtr(a4)        ; ...and save it
  435.     moveq    #0,d0
  436.     move.l    _ProgramName(a4),a0    ; find length of program name
  437.  
  438.     ifd    AUTOREQ
  439.     move.l    a0,PName(a4)
  440.     endc
  441.  
  442.     subq.l    #1,a0
  443.     move.b    (a0),d0
  444.     addq.l    #4,d0            ; adjust for shift
  445.     lsr.l    #2,d0
  446.     move.l    d0,NameLen(a4)        ; store length
  447.     add.l    d0,FAILlen(a4)        ; and sub-chunk total
  448.  
  449.     moveq    #0,d0            ; clear d0 for use
  450.     lea    VBlankFrequency(a6),a0    ; set up a0 to find correct data
  451.     move.b    (a0)+,d0        ; get just in case
  452.     move.l    d0,VBlankFreq(a4)    ; ...so we can figure what
  453.     move.b    (a0),d0         ; ...type of machine
  454.     move.l    d0,PowerSupFreq(a4)    ; ...we're working on
  455.  
  456.     lea    start-4(pc),a0        ; get seglist ptr
  457.     moveq    #-1,d0            ; always at least 1
  458. 2$:
  459.     addq.l    #1,d0
  460.     move.l    (a0),d1         ; find end of list
  461.     beq.s    3$
  462.     lsl.l    #2,d1            ; BPTR!!!!!
  463.     move.l    d1,a0
  464.     bra.s    2$
  465. 3$:
  466.     add.l    d0,SegCount(a4)     ; store # of seglist pointers
  467.     lsl.l    #1,d0            ; multiply by 2 for longword count
  468.     add.l    d0,FAILlen(a4)        ; and sub-chunk length
  469.  
  470.     move.l    StackTop(a4),d0     ; get top of stack
  471.     sub.l    StackPtr(a4),d0     ; find number of bytes used
  472.     addq.l    #4,d0            ; adjust for longword conversion
  473.     lsr.l    #2,d0            ; convert from bytes to long
  474.     move.l    d0,StackLen(a4)     ; and save
  475.     add.l    d0,s2len(a4)        ; and sub-chunk total
  476.  
  477.     move.l    a5,-(sp)        ; save a5 for later
  478.     callsys    Forbid            ; don't let 'em change while we ask
  479.     move.l    MemList+LH_HEAD(a6),d0    ; first node in MemList
  480. checkchip:
  481.     move.l    d0,a5            ; move node address to address reg
  482.     move.w    MH_ATTRIBUTES(a5),d4    ; get node attributes
  483.     btst    #MEMB_CHIP,d4        ; is it chip?
  484.     beq.s    checkfast        ; no, go on
  485.     lea    chipAvail(a4),a3
  486.     bsr.w    AddIt
  487. checkfast:
  488.     btst    #MEMB_FAST,d4        ; is it fast?
  489.     beq.s    next            ; no, go on
  490.     lea    fastAvail(a4),a3
  491.     bsr.w    AddIt
  492. next:
  493.     move.l    LN_SUCC(a5),d0        ; get address of next node
  494.     bne.s    checkchip        ; ...and loop back if valid
  495.     callsys    Permit            ; allow others access again
  496.     move.l    #MEMF_CHIP+MEMF_LARGEST,d1 ; to find largest hunk in chip ram
  497.     callsys    AvailMem
  498.     move.l    d0,chipLargest(a4)    ; store
  499.     move.l    #MEMF_FAST+MEMF_LARGEST,d1 ; to find largest hunk in fast ram
  500.     callsys    AvailMem
  501.     move.l    d0,fastLargest(a4)    ; store
  502.     move.l    (sp)+,a5        ; and restore a5
  503.  
  504.     ifd    AUTOREQ
  505.     moveq    #0,d0            ; PosFlag
  506.     move.l    d0,d1            ; NegFlag
  507.     move.l    d0,a0            ; 0 means use current window
  508.     lea    IText1(a4),a1        ; Body Text
  509.     lea    IText5(a4),a2        ; Positive Gadget Text
  510.     lea    IText6(a4),a3        ; Negative Gadget Text
  511.     moveq    #1,d2
  512.     lsl.l    #8,d2            ; quick way to set Width
  513.     moveq    #76,d3            ; Height
  514.     move.l    IntuiBase(a4),a6    ; get intuition library pointer
  515.     jsr    -$15c(A6)        ; callsys    AutoRequest
  516.     move.l    AbsExecBase.W,a6
  517.     tst.l    d0            ; save SnapShot?
  518.     beq.s    GExit2            ; no, just exit
  519.     endc
  520.  
  521.     move.l    DOSBase(a4),a6
  522.     lea    DumpName(a4),a0     ; get name of output file
  523.     move.l    a0,d1
  524.     move.l    #MODE_NEWFILE,d2    ; create new file
  525.     callsys    Open
  526.     bne.s    4$
  527.     lea    DumpPath(a4),a0     ; if error in current dir, try DF1:
  528.     move.l    a0,d1
  529.     move.l    #MODE_NEWFILE,d2
  530.     callsys    Open
  531.     bne.s    4$
  532.     move.b    #'0',DumpPath+3(a4)    ; still error?    Try DF0:
  533.     lea    DumpPath(a4),a0
  534.     move.l    a0,d1
  535.     move.l    #MODE_NEWFILE,d2
  536.     callsys    Open
  537.  
  538.     ifnd    AUTOREQ
  539.     bne.s    4$            ; if no error, continue (finally!)
  540.     move.l    GConsole(a4),d1
  541.     beq.w    GExit2
  542.     lea    failmsg(a4),a0
  543.     move.l    a0,d2
  544.     move.l    #23,d3
  545.     callsys    Write
  546.     endc
  547.  
  548.     bra.w    GExit2            ; else, print msg & DIE gracefully
  549. 4$:
  550.     move.l    d0,d5            ; save file handle for Write
  551.     move.l    d0,fp(a4)        ; ...and in a safe place for later
  552.     move.l    d5,d1            ; get file handle
  553.     lea    PGTB(a4),a0        ; first part of fixed
  554.     move.l    a0,d2
  555.     move.l    #chunk_len_1,d3     ; length of first
  556.     callsys    Write            ; ...since it gets written over
  557.  
  558.     move.l    d5,d1            ; get file handle
  559.     move.l    _ProgramName(a4),d2    ; get address of program name
  560.     move.l    NameLen(a4),d3        ; get # longs in program name
  561.     lsl.l    #2,d3            ; ..and convert to bytes
  562.     callsys    Write
  563.  
  564.     move.l    d5,d1            ; get file handle
  565.     lea    Environment(a4),a0    ; second part of fixed
  566.     move.l    a0,d2
  567.     move.l    #chunk_len_2,d3     ; length of second part
  568.     callsys    Write
  569.  
  570.     lea    start-8(pc),a0        ; address of seglist (size of seg)
  571.     move.l    (a0)+,d0        ; segsize
  572.     move.l    d0,TempStore+4(a4)    ; save it
  573.     move.l    a0,TempStore(a4)    ; store first number
  574.     move.l    SegCount(a4),d4
  575. 5$:
  576.     move.l    d5,d1            ; get file handle
  577.     move.l    TempAddr(a4),d2     ; address of write buffer
  578.     moveq    #TempSize,d3        ; size of segment pointer
  579.     callsys    Write
  580.     move.l    TempStore(a4),a0    ; retrieve pointer
  581.     move.l    (a0),d0         ; get next seg pointer
  582.     lsl.l    #2,d0            ; adjust
  583.     move.l    d0,TempStore(a4)    ; ..and save
  584.     move.l    d0,a0
  585.     move.l    -4(a0),d0        ; get segsize
  586.     move.l    d0,TempStore+4(a4)    ; ...and save it
  587.     subq.l    #1,d4            ; done yet?
  588.     bne.s    5$            ; no, do next
  589.  
  590.     tst.l    _FMEM(a4)        ; do they want memory reported?
  591.     beq.s    55$            ; no, forget it
  592.     move.l    d5,d1
  593.     lea    subFMEM(a4),a0
  594.     move.l    a0,d2
  595.     move.l    #FMEMlen,d3
  596.     callsys    Write
  597.  
  598. 55$:
  599.     move.l    d5,d1            ; (get the idea?)
  600.     lea    subREGS(a4),a0        ; third part of fixed
  601.     move.l    a0,d2
  602.     move.l    #chunk_len_3,d3     ; length of third
  603.     callsys    Write
  604.  
  605.     move.l    StackLen(a4),d0     ; get length of stack used
  606.     cmpi.l    #2048,d0        ; > 8k ?
  607.     bgt.s    6$            ; yes, dump two chunks
  608.     move.l    d5,d1
  609.     lea    STAK2(a4),a0        ; whole stack chunk
  610.     move.l    a0,d2
  611.     moveq    #STAK2len,d3        ; length of fixed part
  612.     callsys    Write
  613.  
  614.     move.l    d5,d1
  615.     move.l    StackPtr(a4),d2     ; address of stack
  616.     move.l    StackLen(a4),d3     ; get # longwords on stack
  617.     lsl.l    #2,d3            ; ..and convert to bytes
  618.     callsys    Write
  619.     bra.s    7$
  620. 6$:
  621.     move.l    d5,d1
  622.     lea    STAK3(a4),a0        ; top4k chunk
  623.     move.l    a0,d2
  624.     moveq    #STAK3len,d3        ; length of fixed part
  625.     callsys    Write
  626.  
  627.     move.l    d5,d1
  628.     move.l    StackTop(a4),d2     ; find top of stack
  629.     sub.l    #4096,d2        ; find top-4k
  630.     move.l    #4096,d3        ; # bytes to write
  631.     callsys    Write
  632.  
  633.     move.l    d5,d1
  634.     lea    STAK4(a4),a0        ; bottom4k chunk
  635.     move.l    a0,d2
  636.     moveq    #STAK4len,d3        ; length of fixed part
  637.     callsys    Write
  638.  
  639.     move.l    d5,d1
  640.     move.l    StackPtr(a4),d2     ; current stack address
  641.     move.l    #4096,d3        ; # bytes to write
  642.     callsys    Write
  643. 7$:
  644.     move.l    _STAKOffset(a4),d3
  645.     beq.s    8$
  646.     lsr.l    #2,d3
  647.     addq.l    #1,d3
  648.     move.l    d3,_STAKOffset(a4)
  649.     addq.l    #1,d3
  650.     move.l    d5,d1
  651.     lea    STAK5(a4),a0
  652.     move.l    a0,d2
  653.     moveq    #STAK5len,d3
  654.     callsys    Write
  655.  
  656.     move.l    d5,d1
  657.     move.l    StackPtr(a4),d2
  658.     move.l    _STAKOffset(a4),d3
  659.     subq.l    #1,d3
  660.     move.l    StackLen(a4),d4
  661.     cmp.l    d3,d4
  662.     bge.s    75$
  663.     move.l    StackLen(a4),d3
  664. 75$:
  665.     lsl.l    #2,d3
  666.     callsys    Write
  667. 8$:
  668.     tst.l    _ONGURU(A4)        ; user GURU function?
  669.     beq.s    9$
  670.     move.l    d5,-(sp)
  671.     move.l    d5,d1
  672.     lea    UDAT(a4),a0
  673.     move.l    a0,d2
  674.     move.l    #UDATlen,d3
  675.     callsys    Write
  676.     move.l    d5,d1
  677.     moveq    #0,d2            ; zero offset
  678.     moveq    #1,d3            ; ...from EOF
  679.     callsys    Seek
  680.     move.l    d0,SeekStore(a4)
  681.     move.l    _ONGURU(a4),a0
  682.     jsr    (a0)
  683.     addq.l    #4,sp
  684. 9$:
  685.     move.l    fp(a4),d5
  686.     move.l    d5,d1
  687.     moveq    #0,d2            ; offset from EOF
  688.     moveq    #1,d3            ; OFFSET_END
  689.     callsys    Seek            ; Seek returns OLD position
  690.     move.l    d0,d1
  691.     andi.l    #3,d1            ; did user write even longwords?
  692.     beq.s    10$            ; Yep!    Nice Human.
  693.     move.l    d1,d6            ; Nope, save for later.
  694.     clr.l    TempStore(a4)        ; clear temp storage
  695.     move.l    d5,d1
  696.     move.l    TempAddr(a4),d2
  697.     moveq    #4,d3
  698.     sub.l    d6,d3            ; find how many NULLs to pad
  699.     callsys    Write
  700.     bra.s    9$
  701. 10$:
  702.     tst.l    SeekStore(a4)        ; did we write UDAT?
  703.     beq.s    11$            ; nope!
  704.     sub.l    SeekStore(a4),d0    ; find length of UDAT section
  705.     lsr.l    #2,d0            ; adjust to longwords
  706.     move.l    d0,TempStore(a4)    ; save UDAT length for write
  707.     move.l    d5,d1
  708.     move.l    SeekStore(a4),d2    ; find where to write it
  709.     subq.l    #4,d2
  710.     moveq    #-1,d3            ; OFFSET_BEGINNING
  711.     callsys    Seek
  712.     move.l    d5,d1
  713.     move.l    TempAddr(a4),d2
  714.     move.l    #4,d3
  715.     callsys    Write            ; write length of UDAT field to file
  716. 11$:
  717.     move.l    d5,d1
  718.     moveq    #0,d2            ; offset to 'Length' field
  719.     moveq    #1,d3            ; OFFSET_END
  720.     callsys    Seek            ; make sure we are at end of file
  721.     move.l    d5,d1
  722.     moveq    #4,d2            ; offset to 'Length' field
  723.     moveq    #-1,d3            ; OFFSET_BEGINNING
  724.     callsys    Seek
  725.     subq.l    #8,d0            ; adjust total length
  726.     lsr.l    #2,d0            ; adjust to longwords
  727.     move.l    d0,TempStore(a4)    ; save for write
  728.     move.l    d5,d1
  729.     move.l    TempAddr(a4),d2
  730.     move.l    #4,d3
  731.     callsys    Write            ; write 'Length' field
  732. GExit1:
  733.     move.l    fp(a4),d1
  734.     beq.s    GExit2
  735.     move.l    DOSBase(a4),a6
  736.     callsys    Close
  737.  
  738.     ifnd    AUTOREQ
  739.     move.l    GConsole(a4),d1
  740.     beq.s    GExit2
  741.     lea    success(a4),a0
  742.     move.l    a0,d2
  743.     move.l    #32,d3
  744.     callsys    Write
  745.     endc
  746. GExit2:
  747.     move.l    TaskID(a4),a6
  748.     move.l    AbsExecBase.W,a6
  749.     moveq    #$47,d0
  750.     bra.w    exit2
  751.  
  752. *-----------------------------------------------------------------------
  753. * AddIt:    routine to add memory parts to variables
  754.  
  755. AddIt:
  756.     move.l    MH_FREE(a5),d0
  757.     add.l    d0,(a3)         ; add to available
  758.     move.l    MH_UPPER(a5),d0
  759.     sub.l    MH_LOWER(a5),d0
  760.     add.l    d0,4(a3)        ; add to Max section
  761.     rts
  762.     endc
  763.  
  764.         
  765.         section   __MERGED,DATA
  766. *
  767.     xref    DOSBase
  768.  
  769.     xdef    NULL,SysBase,WBenchMsg
  770.     xdef    curdir,_mbase,_mnext,_msize,_tsize
  771.     xdef    _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  772.     xdef    _SIGINT
  773.     xdef    _ProgramName,_StackPtr,_base
  774.  
  775.     ifd    CATCH
  776.     xdef    _ONGURU,_FMEM,_STAKOffset
  777.     endc
  778. *
  779. NULL        dc.l    0        *
  780. _base        dc.l    0        * base of stack
  781. _mbase        dc.l    0        * base of memory pool
  782. _mnext        dc.l    0        * next available memory location
  783. _msize        dc.l    0        * size of memory pool
  784. _tsize        dc.l    0        * total size?
  785. _oserr:
  786. _OSERR        dc.l    0
  787. _FPERR        dc.l    0
  788. _SIGFPE     dc.l    0
  789. _SIGINT     dc.l    0
  790. _ONERR        dc.l    0
  791. _ONEXIT     dc.l    0
  792. _ONBREAK    dc.l    0
  793. curdir        dc.l    0
  794. SysBase     dc.l    0
  795. WBenchMsg    dc.l    0
  796. oldtrapcode     dc.l    0
  797. oldtrapdata     dc.l    0
  798. _StackPtr    dc.l    0
  799. stdin        dc.l    0
  800. _ProgramName    dc.l    0
  801.  
  802.     ifd    CATCH
  803. _ONGURU     dc.l    0
  804. IntuiBase    dc.l    0
  805. TaskID        dc.l    0
  806.     ifnd    AUTOREQ
  807. GConsole    dc.l    0
  808. failmsg     dc.b    7,'Can''t write SnapShot!',10
  809. success     dc.b    7,'GURU caught; SnapShot written!',10
  810.     endc
  811.     cnop    0,4
  812. _FMEM        dc.l    0
  813. fp        dc.l    0        ; save SnapShot file pointer
  814. DumpPath    dc.b    'DF1:'
  815. DumpName    dc.b    'SnapShot.TB',0
  816. SeekStore    dc.l    0
  817. TempAddr    dc.l    0        ; Storage for &TempStore
  818. TempStore    dc.l    0,0        ; Temporary storage for BPTR -> APTR
  819. TempSize    equ    *-TempStore
  820.  
  821.     cnop    0,4
  822.     ifd    AUTOREQ
  823. TAttr:                ; Text attributes for font
  824.     dc.l    TName        ; name of font
  825.     dc.w    TOPAZ_EIGHTY    ; font size
  826.     dc.b    FS_NORMAL    ; font style
  827.     dc.b    FPF_ROMFONT    ; font preferences
  828. TName:
  829.     dc.b    'topaz',0
  830.     cnop    0,4
  831.  
  832. IText1:             ; Text definitions for AutoReq call
  833.     dc.b    3,0,RP_JAM1,0    ; front & back pens, drawmode and filler byte
  834.     dc.w    6,4        ; XY origin relative to container TopLeft
  835.     dc.l    TAttr        ; font pointer or NULL for default
  836.     dc.l    ITextText1    ; pointer to text
  837.     dc.l    IText2        ; next IntuiText structure
  838. ITextText1:
  839.     dc.b    'Program:',0
  840.     cnop 0,4
  841. IText2:
  842.     dc.b    3,0,RP_JAM1,0
  843.     dc.w    78,4
  844.     dc.l    TAttr
  845. PName    dc.l    0
  846.     dc.l    IText3
  847.     cnop    0,4
  848. IText3:
  849.     dc.b    3,0,RP_JAM1,0
  850.     dc.w    55,16
  851.     dc.l    TAttr
  852.     dc.l    ITextText3
  853.     dc.l    IText4
  854. ITextText3:
  855.     dc.b    'I caught a GURU!',0
  856.     cnop 0,4
  857. IText4:
  858.     dc.b    3,0,RP_JAM1,0
  859.     dc.w    20,28
  860.     dc.l    TAttr
  861.     dc.l    ITextText4
  862.     dc.l    NULL
  863. ITextText4:
  864.     dc.b    'Should I make a SnapShot?',0
  865.     cnop 0,4
  866. IText5:
  867.     dc.b    3,0,RP_JAM1,0
  868.     dc.w    6,4
  869.     dc.l    TAttr
  870.     dc.l    ITextText5
  871.     dc.l    NULL
  872. ITextText5:
  873.     dc.b    'YES',0
  874.     cnop 0,4
  875. IText6:
  876.     dc.b    3,0,RP_JAM1,0
  877.     dc.w    7,4
  878.     dc.l    TAttr
  879.     dc.l    ITextText6
  880.     dc.l    NULL
  881. ITextText6:
  882.     dc.b    'NO',0
  883.     endc
  884.  
  885.     cnop 0,4
  886.  
  887. *--------------------------------------------------------------------------
  888. * New IFF chunk format -
  889. *    PGTB = Program Traceback, header for chunk
  890. *    FAIL = reason for and environment of crash
  891. *    REGS = registers at time of crash, including PC and CCR
  892. *    VERS = version, revision, name of this program
  893. *    STAK = ENTIRE stack at time of crash or, alternately,
  894. *        the top and bottom 4k if the stack used is > 8k
  895. *    UDAT = optional user data dump (if _ONGURU is set to a
  896. *        function pointer in the user's program)
  897. *--------------------------------------------------------------------------
  898.  
  899. PGTB        dc.b    'PGTB'
  900. Length        dc.l    0        ; length of chunk (in longwords)
  901.  
  902. subFAIL     dc.b    'FAIL'
  903. FAILlen     dc.l    9
  904. NameLen     dc.l    0        ; length of program name
  905. chunk_len_1    equ    *-PGTB
  906. Environment    dc.l    0        ; CPU (, Math)
  907. VBlankFreq    dc.l    0        ;    PAL = 50, NTSC = 60 (approx.)
  908. PowerSupFreq    dc.l    0        ; Europe = 50,    USA = 60 (approx.)
  909. Starter     dc.l    0        ; 0 = WB, -1 = CLI
  910. GURUNum     dc.l    0        ; cause of crash (GURU #)
  911. SegCount    dc.l    1        ; # hunks in seglist
  912. chunk_len_2    equ    *-Environment
  913.  
  914. subFMEM     dc.b    'FMEM'        ; FMEM - free memory at crash
  915.         dc.l    6
  916. chipAvail    dc.l    0        ; available chip memory
  917. chipMax     dc.l    0        ;    maximum    chip memory
  918. chipLargest    dc.l    0        ;    largest    chip memory
  919. fastAvail    dc.l    0        ; available fast memory
  920. fastMax     dc.l    0        ;    maximum    fast memory
  921. fastLargest    dc.l    0        ;    largest    fast memory
  922. FMEMlen     equ    *-subFMEM
  923.  
  924. subREGS     dc.b    'REGS'        ; REGS - register storage field
  925. REGSlen     dc.l    18
  926. GURUAddr    dc.l    0        ; PC at time of crash
  927. Flags        dc.l    0        ; Condition Code Register (CCR)
  928. DDump        dc.l    0,0,0,0,0,0,0,0 ; data registers
  929. ADump        dc.l    0,0,0,0,0,0,0    ; address registers
  930. A7Store     dc.l    0
  931.  
  932. subVERS     dc.b    'VERS'        ; VERS - program version field
  933.         dc.l    6
  934.         dc.l    VERSION     ; version #
  935.         dc.l    REVISION    ; revision #
  936.         dc.l    3        ; length of name of program
  937.         IFD    RESIDENT
  938.         dc.b    'catchres.o',0,0 ; name
  939.         ENDC
  940.         IFND    RESIDENT
  941.         dc.b    'catch.o   ',0,0 ; name
  942.         ENDC
  943.  
  944. subSTAK     dc.b    'STAK'        ; STAK - stack field
  945. STAKlen     dc.l    4
  946. Type        dc.l    0        ; 0 = Info
  947. StackTop    dc.l    0        ; top of stack pointer
  948. StackPtr    dc.l    0        ; current Stack Pointer
  949. StackLen    dc.l    0        ; # bytes used on stack
  950. chunk_len_3    equ    *-subREGS
  951.  
  952. STAK2        dc.b    'STAK'
  953. s2len        dc.l    1        ; length of subtype
  954.         dc.l    1        ; 1 = whole stack
  955. STAK2len    equ    *-STAK2
  956.  
  957. STAK3        dc.b    'STAK'
  958.         dc.l    1025
  959.         dc.l    2        ; 2 = top 4k of stack
  960. STAK3len    equ    *-STAK3
  961.  
  962. STAK4        dc.b    'STAK'
  963.         dc.l    1025
  964.         dc.l    3        ; 3 = bottom 4k of stack
  965. STAK4len    equ    *-STAK4
  966.  
  967. STAK5        dc.b    'STAK'
  968. _STAKOffset    dc.l    0
  969.         dc.l    4        ; 4 = user defined amount
  970. STAK5len    equ    *-STAK5
  971.  
  972. UDAT        dc.b    'UDAT'
  973.         dc.l    0
  974. UDATlen     equ    *-UDAT
  975.     endc
  976.  
  977.     END
  978.  
  979.